package ar.com.ford.it.fullEconomics.logic;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collection;
import ar.com.ford.it.fullEconomics.FullEconomicsPrs;
import ar.com.ford.it.fullEconomics.exception.FullEconomicsException;
import ar.com.ford.it.fullEconomics.persistence.dao.PaymentPolicyDao;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc05Itemcatgry;
import ar.com.ford.it.fullEconomics.persistence.dto.Teesc06Item;
import ar.com.ford.it.fullEconomics.persistence.dto.Teese04Paypolicy;
import ar.com.ford.it.fullEconomics.persistence.dto.Teese05Paypolvers;
import ar.com.ford.it.fullEconomics.persistence.dto.Teess01Supplier;
import ar.com.ford.it.fullEconomics.struct.PaymentPolicyCreateStruct;
import ar.com.ford.it.fullEconomics.struct.PaymentPolicyDisplayStruct;
import ar.com.ford.it.fullEconomics.util.FullEconomicsDateUtil;
import ar.com.ford.it.fullEconomics.wslx.FullEconomicsWslxUser;
import ar.com.ford.it.webengine.persistence.PersistenceUtil;
import com.ford.it.logging.ILogger;
import com.ford.it.logging.Level;
import com.ford.it.logging.LogFactory;
import com.ford.it.persistence.PersistenceException;

public class PaymentPolicyLogic {
    private static final String CLASS_NAME = PaymentPolicyLogic.class.getName();
    private static final ILogger log = LogFactory.getInstance().getLogger(
            CLASS_NAME);

    /**
     * busca la politicas de pago segun el filtro especificado
     * 
     * @param findPayPolVers
     * @return
     * @throws FullEconomicsException
     */
    public Collection<PaymentPolicyDisplayStruct> findPaymentPolicies(
                                                                      Teese05Paypolvers findPayPolVers)
            throws FullEconomicsException {

        String METHOD_NAME = "findPaymentPolicies";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        Collection<PaymentPolicyDisplayStruct> result;
        try {

            result = dao.findPaymentPolicies(findPayPolVers);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Find Payment Policies Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.FINDBYCODE);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);

        return result;
    }

    /**
     * devuelve las politicas de pago mas recientemente aprobadas filtrando
     * segun los criterios especificados
     * 
     * @param findPayPolVers
     * @return
     * @throws FullEconomicsException
     */
    public Collection<PaymentPolicyDisplayStruct> findLastAprovedPaymentPolicies(
                                                                                 Teese05Paypolvers findPayPolVers)
            throws FullEconomicsException {

        String METHOD_NAME = "findLastAprovedPaymentPolicies";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        Collection<PaymentPolicyDisplayStruct> result;
        try {
            result = dao.findLastAprovedPaymentPolicies(findPayPolVers);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Find Payment Policies Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.FINDBYCODE);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);

        return result;
    }

    /**
     * crea una nueva politica de pago
     * 
     * @param payPolStruct
     * @return
     * @throws FullEconomicsException
     */
    public Teese05Paypolvers createPayPol(PaymentPolicyCreateStruct payPolStruct)
            throws FullEconomicsException {

        String METHOD_NAME = "createPayPol";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        Teese05Paypolvers payPolVersion = new Teese05Paypolvers();
        Teese04Paypolicy payPol = new Teese04Paypolicy();
        FullEconomicsWslxUser user = payPolStruct.getUser();

        Calendar calDateIn = FullEconomicsDateUtil.format(payPolStruct
                .getDateIn());
        Timestamp tsDateIn = new Timestamp(calDateIn.getTimeInMillis());
        Calendar calDateOut = FullEconomicsDateUtil.format(payPolStruct
                .getDateOut());
        Timestamp tsDateOut;
        if (calDateOut == null)
            tsDateOut = FullEconomicsDateUtil.maxDate();
        else
            tsDateOut = new Timestamp(calDateOut.getTimeInMillis());
        Teesc05Itemcatgry itemCategory = new Teesc05Itemcatgry();
        if (payPolStruct.getItem() != null) {
            Teesc06Item item = new Teesc06Item();
            item.setEesc06PlantCodeC(user.getTeesg01Plant());
            item.setEesc06ItemNumberK(new Integer(payPolStruct.getItem()));
            payPol.setTeesc06Item(item);
            payPol.setEese04PaypolItemTypeCodeC("I");
        } else {
            payPol.setEese04PaypolItemTypeCodeC("C");
        }
        itemCategory.setEesc05PlantCodeC(user.getTeesg01Plant());
        itemCategory.setEesc05ItemcatgryNumberK(new Integer(payPolStruct
                .getItemCategory()));
        payPol.setTeesc05Itemcatgry(itemCategory);

        payPol.setEese04PlantCodeC(user.getTeesg01Plant());
        payPol.setEese04CreateUserC(user.getId());
        payPol.setEese04LastUpdtUserC(user.getId());
        payPol.setEese04CreateS(new Timestamp(System.currentTimeMillis()));
        payPol.setEese04LastUpdtS(new Timestamp(System.currentTimeMillis()));

        payPolVersion.setEese05PlantCodeC(user.getTeesg01Plant());
        payPolVersion.setEese05PpyverVersionNumberK(1);
        payPolVersion.setEese05PpyverPercentP(new BigDecimal(payPolStruct
                .getValue()));
        payPolVersion.setEese05PpyverInDateY(tsDateIn);
        payPolVersion.setEese05PpyverOutDateY(tsDateOut);
        payPolVersion.setEese05PpyverCommentsX(payPolStruct.getObservations());
        payPolVersion.setEese05CreateUserC(user.getId());
        payPolVersion.setEese05LastUpdtUserC(user.getId());
        payPolVersion
                .setEese05CreateS(new Timestamp(System.currentTimeMillis()));
        payPolVersion.setEese05LastUpdtS(new Timestamp(System
                .currentTimeMillis()));

        if (payPolStruct.getSupplierClass() != null
                && payPolStruct.getSupplierCode() != null) {
            Teess01Supplier supplier = new Teess01Supplier();
            supplier.setEess01PlantCodeC(user.getTeesg01Plant());
            supplier.setEess01SupplierClassCodeC(payPolStruct
                    .getSupplierClass());
            supplier.setEess01SupplierCodeC(payPolStruct.getSupplierCode());
            payPol.setTeess01Supplier(supplier);
        }

        String[] fields = new String[1];
        Object[] values = new Object[1];

        try {
            PersistenceUtil.newTransaction();
            fields[0] = "eese04PlantCodeC";
            values[0] = payPolStruct.getUser().getTeesg01Plant();
            Integer lastCode = dao.getMax(new Teese04Paypolicy(), fields,
                    values, "eese04PaypolNumberK");
            payPol.setEese04PaypolNumberK(lastCode + 1);
            payPolVersion.setTeese04Paypolicy(payPol);

            dao.createNewPayPolicy(payPolVersion);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Payment Policies Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.CREATE);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return payPolVersion;
    }

    /**
     * crea una nueva version de una politica de pago ya existente
     * 
     * @param payPolVersion
     * @param user
     * @return
     * @throws FullEconomicsException
     */
    public Teese05Paypolvers createPayPolVers(Teese05Paypolvers payPolVersion,
                                              FullEconomicsWslxUser user)
            throws FullEconomicsException {

        String METHOD_NAME = "createPayPolVers";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();

        payPolVersion.setEese05PlantCodeC(user.getTeesg01Plant());
        payPolVersion.setEese05CreateUserC(user.getId());
        payPolVersion
                .setEese05CreateS(new Timestamp(System.currentTimeMillis()));
        payPolVersion.setEese05LastUpdtUserC(user.getId());
        payPolVersion.setEese05LastUpdtS(new Timestamp(System
                .currentTimeMillis()));

        String[] fields = new String[2];
        Object[] values = new Object[2];

        try {
            PersistenceUtil.newTransaction();
            fields[0] = "eese05PlantCodeC";
            fields[1] = "teese04Paypolicy";
            values[0] = user.getTeesg01Plant();
            values[1] = payPolVersion.getTeese04Paypolicy();
            Integer lastCode = dao.getMax(new Teese05Paypolvers(), fields,
                    values, "eese05PpyverVersionNumberK");
            payPolVersion.setEese05PpyverVersionNumberK(lastCode + 1);

            dao.createNewPayPolicy(payPolVersion);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Payment Policie version Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.CREATEVERSION);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return payPolVersion;
    }

    /**
     * actualiza los cambios hechos en la version de la politica de pago
     * 
     * @param payPolVersion
     * @param user
     * @throws FullEconomicsException
     */
    public void updateVersion(Teese05Paypolvers payPolVersion,
                              FullEconomicsWslxUser user)
            throws FullEconomicsException {

        String METHOD_NAME = "updateVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        Teese05Paypolvers workingCopy = null;

        try {
            PersistenceUtil.newTransaction();
            PersistenceUtil.getPersistenceManager().clearCache();
            workingCopy = dao.getPaymentPolicyVersionForUpdate(payPolVersion
                    .getTeese04Paypolicy().getEese04PaypolNumberK(),
                    payPolVersion.getEese05PpyverVersionNumberK(), user
                            .getTeesg01Plant());
            workingCopy.setEese05PpyverPercentP(payPolVersion
                    .getEese05PpyverPercentP());
            workingCopy.setEese05PpyverInDateY(payPolVersion
                    .getEese05PpyverInDateY());
            workingCopy.setEese05PpyverOutDateY(payPolVersion
                    .getEese05PpyverOutDateY());
            workingCopy.setEese05PpyverCommentsX(payPolVersion
                    .getEese05PpyverCommentsX());
            workingCopy.setEese05LastUpdtUserC(user.getId());
            workingCopy.setEese05LastUpdtS(new Timestamp(System
                    .currentTimeMillis()));
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Payment Policie version Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.UPDATEVERSION);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * propone la politica de pago para ser aprovada
     * 
     * @param payPolVersion
     * @param user
     * @throws FullEconomicsException
     */
    public void proposePaymentPolicy(Teese05Paypolvers payPolVersion,
                                     FullEconomicsWslxUser user)
            throws FullEconomicsException {

        String METHOD_NAME = "proposePaymentPolicy";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        Teese05Paypolvers workingCopy = null;

        try {
            if (dao.validDateRange(payPolVersion)) {
                PersistenceUtil.newTransaction();
                workingCopy = dao.getPaymentPolicyVersionForUpdate(
                        payPolVersion.getTeese04Paypolicy()
                                .getEese04PaypolNumberK(), payPolVersion
                                .getEese05PpyverVersionNumberK(), user
                                .getTeesg01Plant());
                workingCopy.setEese05PpyverProposalUserC(user.getId());
                workingCopy.setEese05PpyverProposalS(new Timestamp(System
                        .currentTimeMillis()));
                PersistenceUtil.commitTransaction();
            } else {
                throw new FullEconomicsException(
                        new Exception(),
                        FullEconomicsPrs.MessageErrors.PaymentPolicy.INVALIDDATERANGE);
            }
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Payment Policie version Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.CREATEVERSION);
        } catch (FullEconomicsException e) {
            throw e;
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * se aprueva la politica de pago
     * 
     * @param payPolVersion
     * @param user
     * @throws FullEconomicsException
     */
    public void approvePaymentPolicy(Teese05Paypolvers payPolVersion,
                                     FullEconomicsWslxUser user)
            throws FullEconomicsException {

        String METHOD_NAME = "approvePaymentPolicy";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        Teese05Paypolvers workingCopy = null;
        Teese05Paypolvers prevPayPol = null;
        Teese05Paypolvers prevPayPolWorkingCopy = null;

        try {
            if (dao.validDateRange(payPolVersion)) {
                prevPayPol = dao.getPrevAprovedVersion(payPolVersion);
                PersistenceUtil.newTransaction();
                workingCopy = dao.getPaymentPolicyVersionForUpdate(
                        payPolVersion.getTeese04Paypolicy()
                                .getEese04PaypolNumberK(), payPolVersion
                                .getEese05PpyverVersionNumberK(), user
                                .getTeesg01Plant());
                workingCopy.setEese05PpyverApprovalUserC(user.getId());
                workingCopy.setEese05PpyverApprovalS(new Timestamp(System
                        .currentTimeMillis()));
                if (prevPayPol != null) {
                    if (prevPayPol.getEese05PpyverOutDateY().getTime() > payPolVersion
                            .getEese05PpyverInDateY().getTime()) {
                        prevPayPolWorkingCopy = dao
                                .getPaymentPolicyVersionForUpdate(prevPayPol
                                        .getTeese04Paypolicy()
                                        .getEese04PaypolNumberK(), prevPayPol
                                        .getEese05PpyverVersionNumberK(), user
                                        .getTeesg01Plant());
                        Timestamp prevPayPolDateOut = FullEconomicsDateUtil
                                .fechaMas(payPolVersion
                                        .getEese05PpyverInDateY(), -1);
                        prevPayPolWorkingCopy
                                .setEese05PpyverOutDateY(prevPayPolDateOut);
                    }
                }
                PersistenceUtil.commitTransaction();
            } else {
                throw new FullEconomicsException(
                        new Exception(),
                        FullEconomicsPrs.MessageErrors.PaymentPolicy.INVALIDDATERANGE);
            }
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Approve Payment Policie version Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.APPROVAL);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * devuelve la ultima politica de pago aprovada
     * 
     * @param payPolVers
     * @return
     * @throws FullEconomicsException
     */
    public Teese05Paypolvers getPrevAprovedVersion(Teese05Paypolvers payPolVers)
            throws FullEconomicsException {

        String METHOD_NAME = "getPrevAprovedVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        Teese05Paypolvers ret = null;
        try {
            ret = dao.getPrevAprovedVersion(payPolVers);
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Create Payment Policie version Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.APPROVAL);
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
        return ret;
    }

    /**
     * borra la politica de pago pasada por parametro
     * 
     * @param payPolVers
     * @return
     * @throws FullEconomicsException
     */
    public void deletePaymentPolicyVersion(Teese05Paypolvers payPolVers)
            throws FullEconomicsException {

        String METHOD_NAME = "deletePaymentPolicyVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        try {
            PersistenceUtil.newTransaction();
            dao.deletePaymentPolicyVersion(payPolVers);
            PersistenceUtil.commitTransaction();
        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Delete Payment Policie version Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.DELETE);
        }
        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    /**
     * borra la politica de pago pasada por parametro
     * 
     * @param payPolVers
     * @return
     * @throws FullEconomicsException
     */
    public void approveAllPaymentPolicy(
                                        Collection<PaymentPolicyDisplayStruct> payPolVersCol,
                                        FullEconomicsWslxUser user)
            throws FullEconomicsException {

        String METHOD_NAME = "deletePaymentPolicyVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        for (PaymentPolicyDisplayStruct payPol : payPolVersCol) {
            if (payPol.getDisplayVersion().getEese05PpyverProposalUserC() != null
                    && payPol.getDisplayVersion()
                            .getEese05PpyverApprovalUserC() == null) {
                this.approvePaymentPolicy(payPol.getDisplayVersion(), user);
            }
        }

        log.exiting(CLASS_NAME, METHOD_NAME);
    }

    public Teese05Paypolvers getPayPolVersForFullEconimic(
                                                          Teess01Supplier supplier,
                                                          Teesc06Item item,
                                                          Timestamp econLevel)
            throws FullEconomicsException {

        String METHOD_NAME = "deletePaymentPolicyVersion";
        log.entering(CLASS_NAME, METHOD_NAME);

        PaymentPolicyDao dao = new PaymentPolicyDao();
        Collection<PaymentPolicyDisplayStruct> payPolVersColl;
        Teese05Paypolvers payPolVers = new Teese05Paypolvers();
        Teese05Paypolvers ret = null;
        Teese04Paypolicy payPol = new Teese04Paypolicy();
        try {
            payPolVers.setEese05PlantCodeC(supplier.getEess01PlantCodeC());
            payPol.setTeess01Supplier(supplier);
            payPol.setTeesc06Item(item);
            payPolVers.setTeese04Paypolicy(payPol);
            payPolVersColl = dao.findPaymentPolicies(payPolVers);
            if (!payPolVersColl.isEmpty()) {
                ret = this.getPayPolVersInDate(payPolVersColl, econLevel);
            } else {
                payPolVers.getTeese04Paypolicy().setTeesc06Item(null);
                payPolVers.getTeese04Paypolicy().setTeesc05Itemcatgry(
                        item.getTeesc05Itemcatgry());
                payPolVersColl = dao.findPaymentPolicies(payPolVers);
                ret = this.getPayPolVersInDate(payPolVersColl, econLevel);
                if (ret == null) {
                    payPolVers.getTeese04Paypolicy().setTeess01Supplier(null);
                    payPolVers.getTeese04Paypolicy().setTeesc06Item(item);
                    payPolVers.getTeese04Paypolicy().setTeesc05Itemcatgry(null);
                    payPolVersColl = dao.findPaymentPolicies(payPolVers);
                    ret = this.getPayPolVersInDate(payPolVersColl, econLevel);
                    if (ret == null) {
                        payPolVers.getTeese04Paypolicy().setTeesc06Item(null);
                        payPolVers.getTeese04Paypolicy().setTeesc05Itemcatgry(
                                item.getTeesc05Itemcatgry());
                        payPolVersColl = dao.findPaymentPolicies(payPolVers);
                        ret = this.getPayPolVersInDate(payPolVersColl,
                                econLevel);
                    }
                }
            }

        } catch (PersistenceException e) {
            log.logp(Level.SEVERE, CLASS_NAME, METHOD_NAME,
                    "Delete Payment Policie version Exception", e);
            throw new FullEconomicsException(e,
                    FullEconomicsPrs.MessageErrors.PaymentPolicy.DELETE);
        }

        return ret;
    }

    private Teese05Paypolvers getPayPolVersInDate(
                                                  Collection<PaymentPolicyDisplayStruct> coll,
                                                  Timestamp date) {
        Teese05Paypolvers ret = null;
        for (PaymentPolicyDisplayStruct payPolVersTemp : coll) {
            if (payPolVersTemp.getDisplayVersion().getEese05PpyverInDateY()
                    .getTime() < date.getTime()
                    && payPolVersTemp.getDisplayVersion()
                            .getEese05PpyverOutDateY().getTime() > date
                            .getTime()) {
                ret = payPolVersTemp.getDisplayVersion();
            }
        }
        return ret;
    }
    
}
